/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package systole.view.workers;

import java.util.Iterator;
import javax.swing.SwingWorker;
import systole.domain.analysis.Analysis;
import systole.domain.analysis.results.AnalysisResult;
import systole.domain.signals.FinalSignal;
import systole.domain.signals.Segment;
import systole.domain.signals.SelectedSegment;
import systole.ioHandling.logs.SystoleLogger;
import systole.math.SimpleDerivative;
import systole.processor.SignalAnalyzer;
import systole.processor.SignalProcessor;
import systole.view.charts.XYChart;
import systole.view.tabs.controllers.AnalysisController;

/**
 *
 * @author jmj
 */
public class WorkerProcessor extends SwingWorker<Void, Void> {

    private Analysis currentAnalysis;
    private AnalysisController parentControl;
    private XYChart allCharts;
    private XYChart derivates;
    private XYChart finalSegment;
    private boolean processed;
    private AnalysisResult analysisResult;
    private FinalSignal finalSignal;

    /**
     * Complete constructor.
     * @param analysisController
     * 
     */
    public WorkerProcessor(AnalysisController analysisController) {
        super();
        this.parentControl = analysisController;
        this.processed = false;
        this.currentAnalysis = this.parentControl.getAnalysis();
    }

    @Override
    protected Void doInBackground() {

        try {
            if ((this.parentControl.getSelectionModel().getSelectedSegments() != null)) {

                SignalProcessor processor = new SignalProcessor();
                //Returns a signal composed by the selected segments
                Segment segment = processor.process(this.parentControl.getSelectionModel().getSelectedSegments());

                if ((segment != null) && (!segment.isEmpty())) {

                    if (!this.parentControl.isWaitingForClose()) {
                        this.doCharts(segment);
                    }

                    segment = segment.normalize();

                    finalSignal = processor.calcDerivatives(segment, new SimpleDerivative());

                    if (!this.parentControl.isWaitingForClose()) {
                        this.doDerivatives(segment);
                    }
                    //Calculo de parámetros
                    SignalAnalyzer analyzer = new SignalAnalyzer(this.currentAnalysis.getSignalFrequency().getFrequency(), this.finalSignal, this.getHeartRate());
                    analysisResult = analyzer.calculateParameters();

                    this.processed = true;
                }
            }
        } catch (Exception e) {
            SystoleLogger.getInstance().logError(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    private void doDerivatives(Segment segment) {
        this.derivates = new XYChart("Derivadas", "Tiempo (ms)", "Amplitud (%)");
        double frequency = this.currentAnalysis.getSignalFrequency().getFrequency().doubleValue();
        this.derivates.addSeries("Latido", segment.toDoubleArray(), frequency);
        this.derivates.addSeries("Derivada 1ra", finalSignal.getFirstDerivatite().toDoubleArray(), frequency);
        this.derivates.addSeries("Derivada 2da", finalSignal.getSecondDerivative().toDoubleArray(), frequency);
        this.derivates.addSeries("Derivada 3ra", finalSignal.getThirdDerivative().toDoubleArray(), frequency);
        this.derivates.addSeries("Derivada 4ta", finalSignal.getFourthDerivative().toDoubleArray(), frequency);
    }

    private void doCharts(Segment segment) {
        this.allCharts = new XYChart("Segmentos", "Muestras", "Amplitud (%)");

        Iterator<SelectedSegment> segments = this.parentControl.getSelectionModel().getSelectedSegments().iterator();
        while (segments.hasNext()) {
            SelectedSegment selectedSegment = segments.next();
            this.allCharts.addSeries("Seg-" + (selectedSegment.getNumber() + 1), selectedSegment.getSegment().toDoubleArray(), 1);
        }

        this.finalSegment = new XYChart("Curva Final", "Tiempo (ms)", "Amplitud (%)");
        this.finalSegment.addSeries("Latido", segment.toDoubleArray(), this.currentAnalysis.getSignalFrequency().getFrequency().doubleValue());
    }

    @Override
    public void done() {

        if (this.processed) {
            this.parentControl.getResultsModel().loadAnalysisResultCalculated(analysisResult, finalSignal);

            // se verifica si se proceso solo para guardar
            if (this.parentControl.isWaitingForClose()) {
                this.parentControl.closeAfterProcess();
                return;
            }

            this.parentControl.getFrmAnalysis().addProcessedCharts(this.allCharts, this.finalSegment, this.derivates);
            this.parentControl.getFrmAnalysis().showFinalPnl();
            this.parentControl.getFrmAnalysis().getJReportView().getPnlReport().loadResult(analysisResult);
            this.parentControl.startReporting();
        }
    }

    public float getHeartRate() {
        if (this.currentAnalysis.getAllSegments().getSegments().isEmpty()) {
            return 0;
        }
        int avg = 0;
        Iterator<Segment> it = this.currentAnalysis.getAllSegments().getSegments().iterator();

        while (it.hasNext()) {
            avg += it.next().size();
        }

        return avg /this.currentAnalysis.getAllSegments().getSegments().size();
    }

}
